package com.xzzz.irda.auth.server.authentication;

import cn.hutool.core.util.StrUtil;
import com.xzzz.irda.auth.core.authorization.Authorization;
import com.xzzz.irda.auth.core.authorization.AuthorizationPhone;
import com.xzzz.irda.auth.core.constants.GrantTypeEnum;
import com.xzzz.irda.auth.core.exception.*;
import com.xzzz.irda.auth.core.AuthBaseProperties;
import com.xzzz.irda.auth.server.AuthServerConfiguration;
import com.xzzz.irda.auth.server.pojo.LoginMetadata;
import com.xzzz.irda.auth.server.service.CaptchaService;
import com.xzzz.irda.auth.server.service.UserDetail;
import com.xzzz.irda.auth.server.service.UserDetailService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;

/**
 *
 * 手机验证码登录
 *
 * @author wangyf
 * 
 */
@Slf4j
public class AuthenticationPhoneManager extends AbstractAuthenticationManager {

    @Autowired
    private UserDetailService userDetailService;

    @Autowired(required = false)
    private CaptchaService captchaService;

    public AuthenticationPhoneManager(
            AuthServerConfiguration authServerConfiguration,
            AuthBaseProperties authBaseProperties) {
        super(authServerConfiguration, authBaseProperties);
    }

    @Override
    public String getGrantType() {
        return GrantTypeEnum.PHONE.getType();
    }

    @Override
    public Authorization authorizationBeforeProcess(Authorization authorization, LoginMetadata login) {
        if (captchaService == null) {
            throw new AuthException(AuthRCode.CAPTCHA_FAULT.getCode(), "无法检查验证码, 不支持该授权方式");
        }

        AuthorizationPhone authorizationPhone = (AuthorizationPhone) authorization;
        authorizationPhone.setPhone(login.getPhone());
        return authorizationPhone;
    }

    @Override
    public UserDetail findUser(Authorization authorization, LoginMetadata login) {
        AuthorizationPhone authorizationPhone = (AuthorizationPhone) authorization;

        final String phone       = authorizationPhone.getPhone();
        final String captchaKey  = login.getMsgCaptchaKey();
        final String captchaCode = login.getMsgCaptchaCode();

        if (StrUtil.isBlank(phone)) {
            throw new AuthException(AuthRCode.PHONE_FAULT);
        }

        if (StrUtil.isBlank(captchaKey) || StrUtil.isBlank(captchaCode) || !captchaService.checkMsgCaptchaCode(phone,captchaKey,captchaCode)) {
            log.error("[AUTHORIZ] 验证码登录失败,验证码错误 > phone:{}, key:{}, code:{}", phone, captchaKey, captchaCode);
            throw new AuthException(AuthRCode.CAPTCHA_FAULT);
        }

        // 获取用户信息并检查
        UserDetail userDetail = userDetailService.loadUserByPhone(phone);
        if (userDetail == null) {
            throw new AuthException(AuthRCode.USER_NOT_EXIST);
        }

        return userDetail;
    }

    @Override
    public Authorization authorizationAfterProcess(Authorization authorization, LoginMetadata loginMetadata) {
        String captchaKey = loginMetadata.getMsgCaptchaKey();
        captchaService.removeMsgCaptchaCode(captchaKey);
        ((AuthorizationPhone) authorization).setPhone(null);
        return authorization;
    }
}
